home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / tcsel003.zip / CLOCK.PAS < prev    next >
Pascal/Delphi Source File  |  1992-10-16  |  5KB  |  129 lines

  1. unit Clock;
  2. {
  3.   Author:  Trevor J Carlsen 
  4.   Purpose: Demonstrate a simple "on screen" clock.
  5.   
  6.   This demo unit works by "hooking" the timer interrupt ($1c). This
  7.   interrupt is called by the hardware interrupt ($08) approximately 18.2
  8.   times every second and normally consists of a simple return instruction
  9.   unless some other application has already hooked it.
  10.   
  11.   Because the routine is called roughly 18 times every second it is
  12.   important that any processing it contains is optimised as much as
  13.   possible.  Obviously the best way to do this is by assembly language but
  14.   in this demo I have used almost pure Turbo Pascal and have set up a
  15.   counter variable and any processing is only done every 6 calls.  This is
  16.   more than sufficient and minimises processing. The routine is by no
  17.   means perfect - there will be a minor irregularity for the final 10
  18.   seconds of each day and for about half a second each hour. Better this
  19.   than to waste valuable processing time in the interrupt by coding it
  20.   out.
  21.   
  22.   Because DOS is not re-entrant it is also important that the routine make
  23.   no calls to any procedure or function that makes use of dos for its
  24.   operation. Thus no writeln, write can be used.  To display the time on
  25.   screen an array is addressed directly to screen memory.  Any changes in
  26.   this array are thus reflected on the screen.  The downside to this is
  27.   that on older CGAs this would cause a "snow" effect and code would be
  28.   needed to eliminate this. It also means that the TP procedure GetTime
  29.   cannot be used.  So the time is calculated from the value stored at the
  30.   clock tick counter location.
  31.   
  32.   To display an on-screen clock all that is required is for a programmer
  33.   to include this unit in the uses declaration of the program.}
  34.   
  35. interface
  36.  
  37. const
  38.   DisplayClock : boolean = true;
  39.  
  40. implementation
  41. { Everything is private to this unit }
  42.  
  43. uses dos;
  44.  
  45. const
  46.   line          = 0;  { Change as required for position of display on screen }
  47.   column        = 72;                               { Top left corner is 0,0 }
  48.   ScreenPos     = (line * 160) + (column * 2);
  49.   Colour        = $1f;                                       { White on Blue }
  50.   ZeroChar      = Colour shl 8 + ord('0'); 
  51.   Colon         = Colour shl 8 + ord(':');
  52. type
  53.   timestr       = array[0..7] of word;
  54.   timeptr       = ^timestr;
  55. var
  56.   time          : timeptr;
  57.   OldInt1c      : pointer;
  58.   ExitSave      : pointer;
  59.  
  60. {$F+}
  61.  procedure Int1cISR; interrupt;
  62.   { This will be called every clock tick by hardware interrupt $08 }
  63.   const
  64.     count       : integer = 0;                  { To keep track of our calls }
  65.   var
  66.     hr          : word absolute $40:$6e;
  67.     ticks       : word absolute $40:$6c; 
  68.                   { This location keeps the number of clock ticks since 00:00}
  69.     min,
  70.     sec         : byte;
  71.     seconds     : word;
  72.   begin
  73.     asm cli end;
  74.     if DisplayClock then begin
  75.       inc(count);
  76.       if count = 6 then { ticks to update the display } begin
  77.         count       := 0;  { equality check and assignment faster than mod 9 }
  78.         seconds     := ticks * longint(10) div 182;       { speed = no reals }
  79.         min         := (seconds div 60) mod 60;
  80.         sec         := seconds mod 60;
  81.  
  82.       { The following statements are what actually display the on-screen time}
  83.  
  84.         time^[0]    := ZeroChar + (hr div 10);         { first char of hours }
  85.         time^[1]    := ZeroChar + (hr mod 10);        { second char of hours }
  86.         time^[2]    := Colon;
  87.         time^[3]    := ZeroChar + (min div 10);      { first char of minutes }
  88.         time^[4]    := ZeroChar + (min mod 10);     { second char of minutes }
  89.         time^[5]    := Colon;
  90.         time^[6]    := ZeroChar + (sec div 10);      { first char of seconds }
  91.         time^[7]    := ZeroChar + (sec mod 10);     { second char of seconds }
  92.       end;  { if count = 6 }
  93.     end;  { if DisplayClock }
  94.     asm         
  95.       sti
  96.       pushf                                  { push flags to set up for IRET }
  97.       call OldInt1c;                              { Call old ISR entry point }
  98.     end;
  99.   end; { Int1cISR }
  100.  
  101. procedure ClockExitProc;
  102.   { This procedure is VERY important as you have hooked the timer interrupt  }
  103.   { and therefore if this is omitted when the unit is terminated your        }
  104.   { system will crash in an unpredictable and possibly damaging way.         }
  105.   begin
  106.     ExitProc := ExitSave;
  107.     SetIntVec($1c,OldInt1c);               { This "unhooks" the timer vector }
  108.   end;
  109. {$F-}
  110.  
  111. procedure Initialise;
  112.   var
  113.     mode : byte absolute $40:$49;
  114.   begin
  115.     if mode = 7 then                                { must be a mono adaptor }
  116.       time := ptr($b000,ScreenPos)
  117.     else                                       { colour adaptor of some kind }
  118.       time := ptr($b800,ScreenPos);      
  119.     GetIntVec($1c,OldInt1c);              { Get old timer vector and save it }
  120.     ExitSave := ExitProc;                          { Save old exit procedure }
  121.     ExitProc := @ClockExitProc;                 { Setup a new exit procedure }
  122.     SetIntVec($1c,@Int1cISR);   { Hook the timer vector to the new procedure }
  123.   end;  { Initialise }  
  124.   
  125. begin 
  126.   Initialise;
  127. end.
  128.  
  129.